<script setup lang="ts">
import { ref, computed, nextTick, watch, watchEffect, onMounted, onUnmounted } from 'vue'
import { Lunar, Solar } from 'lunar-typescript'

const emit = defineEmits(['update:modelValue', 'change'])

const props = defineProps({
  modelValue: {
    type: Date,
    default: () => new Date('2000-01-01')
  },
  // 是否显示时辰选择
  showHour: {
    type: Boolean,
    default: true
  }
})

// 是否显示选择器
const showPicker = ref(false)

// 当前选择的日历类型：1=公历，2=农历
const calendarType = ref(1)

// 当前选择的年、月、日
const selectedYear = ref(new Date().getFullYear())
const selectedMonth = ref(new Date().getMonth() + 1)
const selectedDay = ref(new Date().getDate())

// 获取时辰函数
const getChineseHour = (hours: number) => {
  const hoursToShichen = [
    '早子', '丑初', '丑正', '寅初', '寅正', '卯初', '卯正', '辰初', '辰正', '巳初',
    '巳正', '午初', '午正', '未初', '未正', '申初', '申正', '酉初', '酉正', '戌初',
    '戌正', '亥初', '亥正', '晚子'
  ];
  
  // 通过数学计算映射时辰索引
  return hoursToShichen[hours] as string;
};

// 当前选择的时辰
const selectedHour = ref(getChineseHour(new Date().getHours()))

// 初始化数据
const initPickerData = () => {
  if (props.modelValue) {
    const date = props.modelValue
    selectedYear.value = date.getFullYear()
    selectedMonth.value = date.getMonth() + 1
    selectedDay.value = date.getDate()
    selectedHour.value = getChineseHour(date.getHours())
  }
}

// 监听modelValue变化
watchEffect(() => {
  initPickerData()
})

// 年份列表（1970-2050）
const yearList = computed(() => {
  const years = []
  for (let i = 1970; i <= 2050; i++) {
    years.push(i)
  }
  return years
})

// 月份列表
const monthList = computed(() => {
  return Array.from({ length: 12 }, (_, i) => i + 1)
})

// 日期列表
const dayList = computed(() => {
  if (calendarType.value === 1) {
    // 公历天数
    const year = selectedYear.value
    const month = selectedMonth.value
    const daysInMonth = new Date(year, month, 0).getDate()
    return Array.from({ length: daysInMonth }, (_, i) => i + 1)
  } else {
    // 农历天数 - 使用正确的获取天数方法
    const lunar = Lunar.fromYmd(selectedYear.value, selectedMonth.value, 1)
    // 查找当月的天数 - 使用 getDaysOfMonth 方法
    const daysInMonth = 30  // 默认为30天，大多数农历月是29或30天
    return Array.from({ length: daysInMonth }, (_, i) => i + 1)
  }
})

// 获取农历日期汉字表示
const getLunarDayText = (day: number) => {
  const chineseDay = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十',
    '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十',
    '廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十']
  return chineseDay[day - 1] || ''
}

// 获取农历月份汉字表示
const getLunarMonthText = (month: number) => {
  const chineseMonth = ['正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '冬月', '腊月']
  return chineseMonth[month - 1] || ''
}

// 时辰列表
const hourList = [
  { label: '早子', value: '早子', tip: '00:00-00:59(子)' },
  { label: '丑初', value: '丑初', tip: '01:00-01:59(丑)' },
  { label: '丑正', value: '丑正', tip: '02:00-02:59(丑)' },
  { label: '寅初', value: '寅初', tip: '03:00-03:59(寅)' },
  { label: '寅正', value: '寅正', tip: '04:00-04:59(寅)' },
  { label: '卯初', value: '卯初', tip: '05:00-05:59(卯)' },
  { label: '卯正', value: '卯正', tip: '06:00-06:59(卯)' },
  { label: '辰初', value: '辰初', tip: '07:00-07:59(辰)' },
  { label: '辰正', value: '辰正', tip: '08:00-08:59(辰)' },
  { label: '巳初', value: '巳初', tip: '09:00-09:59(巳)' },
  { label: '巳正', value: '巳正', tip: '10:00-10:59(巳)' },
  { label: '午初', value: '午初', tip: '11:00-11:59(午)' },
  { label: '午正', value: '午正', tip: '12:00-12:59(午)' },
  { label: '未初', value: '未初', tip: '13:00-13:59(未)' },
  { label: '未正', value: '未正', tip: '14:00-14:59(未)' },
  { label: '申初', value: '申初', tip: '15:00-15:59(申)' },
  { label: '申正', value: '申正', tip: '16:00-16:59(申)' },
  { label: '酉初', value: '酉初', tip: '17:00-17:59(酉)' },
  { label: '酉正', value: '酉正', tip: '18:00-18:59(酉)' },
  { label: '戌初', value: '戌初', tip: '19:00-19:59(戌)' },
  { label: '戌正', value: '戌时', tip: '20:00-20:59(戌)' },
  { label: '亥初', value: '亥初', tip: '21:00-21:59(亥)' },
  { label: '亥正', value: '亥正', tip: '22:00-22:59(亥)' },
  { label: '晚子', value: '晚子', tip: '23:00-23:59(子)' }
]

// 切换日历类型
const switchCalendarType = (type: number) => {
  if (type === calendarType.value) return
  
  // 保存当前选择的日期
  const currentDate = getCurrentDate()
  
  // 切换日历类型
  calendarType.value = type
  
  // 转换日期
  if (type === 1) {
    // 农历转公历
    const lunar = Lunar.fromYmd(selectedYear.value, selectedMonth.value, selectedDay.value)
    const solar = lunar.getSolar()
    selectedYear.value = solar.getYear()
    selectedMonth.value = solar.getMonth()
    selectedDay.value = solar.getDay()
  } else {
    // 公历转农历
    const solar = Solar.fromYmd(selectedYear.value, selectedMonth.value, selectedDay.value)
    const lunar = solar.getLunar()
    selectedYear.value = lunar.getYear()
    selectedMonth.value = lunar.getMonth()
    selectedDay.value = lunar.getDay()
  }
}

// 获取当前选择的日期
const getCurrentDate = () => {
//   if (calendarType.value === 1) {
//     // 公历
//     return new Date(selectedYear.value, selectedMonth.value - 1, selectedDay.value)
//   } else {
//     // 农历转公历
//     const lunar = Lunar.fromYmd(selectedYear.value, selectedMonth.value, selectedDay.value)
//     const solar = lunar.getSolar()
//     return new Date(solar.getYear(), solar.getMonth() - 1, solar.getDay())
    //   }
  let date: Date;
  
  if (calendarType.value === 1) {
    // 公历
    date = new Date(selectedYear.value, selectedMonth.value - 1, selectedDay.value)
  } else {
    // 农历转公历
    const lunar = Lunar.fromYmd(selectedYear.value, selectedMonth.value, selectedDay.value)
    const solar = lunar.getSolar()
    date = new Date(solar.getYear(), solar.getMonth() - 1, solar.getDay())
  }
  
  // 根据时辰设置小时
  if (props.showHour && selectedHour.value) {
    // 获取小时对应的数值
    const hourMap: Record<string, number> = {
      '早子': 0,  // 00:00 (早子时)
      '丑初': 1,  // 01:00
      '丑正': 2,  // 01:00
      '寅初': 3,  // 03:00
      '寅正': 4,  // 03:00
      '卯初': 5,  // 05:00
      '卯正': 6,  // 05:00
      '辰初': 7,  // 07:00
      '辰正': 8,  // 07:00
      '巳初': 9,  // 09:00
      '巳正': 10,  // 09:00
      '午初': 11, // 11:00
      '午正': 12, // 11:00
      '未初': 13, // 13:00
      '未正': 14, // 13:00
      '申初': 15, // 15:00
      '申正': 16, // 15:00
      '酉初': 17, // 17:00
      '酉正': 18, // 17:00
      '戌初': 19, // 19:00
      '戌正': 20, // 19:00
      '亥初': 21, // 21:00
      '亥正': 22, // 21:00
      '晚子': 23, // 21:00
    }
    
    // 设置小时，如果是晚子时 (23:00)，特别处理
    const hourText = selectedHour.value
    const hour = hourMap[hourText] || 0
    console.log(hourText,hour)
    // 特殊处理晚子时 (23:00)
    // if (hourText === '子时' && hourMap['亥时'] < hour) {
    //   date.setHours(23)
    // } else {
    //   date.setHours(hour)
      // }
    // if (hourText === '子时' && hourList.findIndex(h => h.value === hourText) === hourList.length - 1) {
    //   date.setHours(23)
    // } else {
    //   date.setHours(hour)
    // }
    date.setHours(hour)
    // 设置分钟为0
    date.setMinutes(0)
    // 设置秒为0
    date.setSeconds(0)
  }
  
  return date
}

// 滚动到选中项
const scrollToSelected = () => {
  // console.log('触发了')
  nextTick(() => {
    // 获取所有选择器容器
    const containers = document.querySelectorAll('.date-picker-container .flex-1.overflow-y-auto')
    
    // 分别滚动各个容器
    containers.forEach((container, index) => {
      if (container instanceof HTMLElement) {
        const selectedElement = container.querySelector('.selected')
        if (selectedElement && selectedElement instanceof HTMLElement) {
          const scrollTop = selectedElement.offsetTop - container.offsetHeight / 2 + selectedElement.offsetHeight / 2
          container.scrollTop = scrollTop
        }
      }
    })
  })
}

// 用于保存滚动事件监听器引用的对象
const scrollListeners = ref<{
  container: HTMLElement;
  listener: (e: Event) => void;
}[]>([])

// 处理滚动事件
const handleScroll = (event: Event, containerIndex: number) => {
  if (!(event.target instanceof HTMLElement)) return
  
  const container = event.target
  const items = Array.from(container.querySelectorAll('.picker-item'))
  if (items.length === 0) return
  
  // 计算中间位置
  const containerMiddle = container.scrollTop + container.offsetHeight / 2
  
  // 找到最接近中间的元素
  let closestItem = items[0]
  let minDistance = Infinity
  
  items.forEach(item => {
    if (item instanceof HTMLElement) {
      const itemMiddle = item.offsetTop + item.offsetHeight / 2
      const distance = Math.abs(containerMiddle - itemMiddle)
      
      if (distance < minDistance) {
        minDistance = distance
        closestItem = item
      }
    }
  })
  if (!closestItem) return
  // 获取最近元素的数据值
  const value = closestItem.getAttribute('data-value')
  if (!value) return
  
  // 根据容器索引更新相应的值
  if (containerIndex === 0) { // 年份
    const year = parseInt(value)
    if (year && year !== selectedYear.value) {
      selectedYear.value = year
    }
  } else if (containerIndex === 1) { // 月份
    const month = parseInt(value)
    if (month && month !== selectedMonth.value) {
      selectedMonth.value = month
    }
  } else if (containerIndex === 2) { // 日期
    const day = parseInt(value)
    if (day && day !== selectedDay.value) {
      selectedDay.value = day
    }
  } else if (containerIndex === 3 && props.showHour) { // 时辰
    if (value !== selectedHour.value) {
      selectedHour.value = value
    }
  }
}

// 设置滚动监听
const setupScrollListeners = () => {
  // 先移除旧的监听器
  removeScrollListeners()
  
  nextTick(() => {
    const containers = document.querySelectorAll('.date-picker-container .flex-1.overflow-y-auto')
    
    containers.forEach((container, index) => {
      if (container instanceof HTMLElement) {
        const listener = (event: Event) => handleScroll(event, index)
        container.addEventListener('scroll', listener)
        scrollListeners.value.push({
          container,
          listener
        })
      }
    })
  })
}

// 移除滚动监听
const removeScrollListeners = () => {
  scrollListeners.value.forEach(({ container, listener }) => {
    container.removeEventListener('scroll', listener)
  })
  scrollListeners.value = []
}

// 监听选项变化，滚动到选中项
watch([selectedYear, selectedMonth, selectedDay, selectedHour, calendarType], () => {
  scrollToSelected()
})

// 确认选择
const confirmPicker = () => {
  const date = getCurrentDate()
  emit('update:modelValue', date)
  emit('change', date)
  showPicker.value = false
  removeScrollListeners()
}

// 取消选择
const cancelPicker = () => {
  showPicker.value = false
  removeScrollListeners()
}

// 显示选择器
const openPicker = () => {
  initPickerData()
  showPicker.value = true
  nextTick(() => {
    scrollToSelected()
    setupScrollListeners()
  })
}

// 组件卸载时清理监听器
onUnmounted(() => {
  removeScrollListeners()
})

// 格式化日期
const formatDate = (date: Date) => {
  if (!date) return '请选择出生日期 (必填)'
  
  // 公历日期
  const solarDate = `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`
  
  // 转换为农历显示
  try {
    const solar = Solar.fromDate(date)
    const lunar = solar.getLunar()
    const lunarYear = lunar.getYear()
    const lunarMonth = getLunarMonthText(lunar.getMonth())
    const lunarDay = getLunarDayText(lunar.getDay())
    // 显示公历和农历以及时辰
    const loarHour = selectedHour.value
    if (props.showHour) {
      return `${solarDate} (农历${lunarMonth}${lunarDay} ${loarHour})`
    } else {
      return `${solarDate} (农历${lunarMonth}${lunarDay})`
    }
  } catch(e) {
    // 如果转换失败，只显示公历日期
    return solarDate
  }
}
</script>

<template>
  <div class="relative">
    <!-- 日期选择器触发器 -->
    <div @click="openPicker" class="cursor-pointer">
      <slot>
        <div class="text-[#996600]">{{ formatDate(modelValue) }}</div>
      </slot>
    </div>

    <!-- 日期选择弹窗 -->
    <div v-if="showPicker" 
      class="fixed inset-0 z-50 flex items-center justify-center"
      @click.self="cancelPicker">
      
      <div class="bg-white w-[92%] rounded-lg overflow-hidden">
        <!-- 日历类型切换 -->
        <div class="flex border-b border-gray-100">
          <button 
            @click="cancelPicker"
            class="flex-1 py-3 text-center text-gray-500">
            取消
          </button>
          
          <div class="flex-1 flex">
            <button 
              @click="switchCalendarType(1)" 
              class="flex-1 py-3 text-center"
              :class="calendarType === 1 ? 'text-orange-500 bg-orange-50 font-bold' : 'text-gray-500'">
              公历
            </button>
            <button 
              @click="switchCalendarType(2)" 
              class="flex-1 py-3 text-center"
              :class="calendarType === 2 ? 'text-orange-500 bg-orange-50 font-bold' : 'text-gray-500'">
              农历
            </button>
          </div>
          
          <button 
            @click="confirmPicker"
            class="flex-1 py-3 text-center text-orange-500 font-bold">
            完成
          </button>
        </div>
        
        <!-- 选择器主体 -->
        <div class="flex overflow-hidden h-[300px] date-picker-container">
          <!-- 年份选择 -->
          <div class="flex-1 overflow-y-auto py-2 text-center">
            <div class="h-[125px]"></div> <!-- 顶部空白占位 -->
            <div v-for="year in yearList" :key="year" 
              class="py-2 mx-2 picker-item"
              :data-value="year"
              :class="selectedYear === year ? 'text-orange-500 font-bold selected' : 'text-gray-700'">
              {{ year }}
            </div>
            <div class="h-[125px]"></div> <!-- 底部空白占位 -->
          </div>
          
          <!-- 月份选择 -->
          <div class="flex-1 overflow-y-auto py-2 text-center">
            <div class="h-[125px]"></div> <!-- 顶部空白占位 -->
            <div v-for="month in monthList" :key="month" 
              class="py-2 mx-2 picker-item"
              :data-value="month"
              :class="selectedMonth === month ? 'text-orange-500 font-bold selected' : 'text-gray-700'">
              <template v-if="calendarType === 1">
                {{ month }}月
              </template>
              <template v-else>
                {{ getLunarMonthText(month) }}
              </template>
            </div>
            <div class="h-[125px]"></div> <!-- 底部空白占位 -->
          </div>
          
          <!-- 日期选择 -->
          <div class="flex-1 overflow-y-auto py-2 text-center">
            <div class="h-[125px]"></div> <!-- 顶部空白占位 -->
            <div v-for="day in dayList" :key="day" 
              class="py-2 mx-2 picker-item"
              :data-value="day"
              :class="selectedDay === day ? 'text-orange-500 font-bold selected' : 'text-gray-700'">
              <template v-if="calendarType === 1">
                {{ day }}
              </template>
              <template v-else>
                {{ getLunarDayText(day) }}
              </template>
            </div>
            <div class="h-[125px]"></div> <!-- 底部空白占位 -->
          </div>
          
          <!-- 时辰选择 (可选) -->
          <div v-if="showHour" class="flex-1 overflow-y-auto py-2 text-center">
            <div class="h-[125px]"></div> <!-- 顶部空白占位 -->
            <div v-for="hour in hourList" :key="hour.value" 
              class="py-2 mx-2 picker-item"
              :data-value="hour.value"
              :class="selectedHour === hour.value ? 'text-orange-500 font-bold selected' : 'text-gray-700'">
              {{ hour.label }}
              <div class="text-xs text-gray-400">{{ hour.tip }}</div>
            </div>
            <div class="h-[125px]"></div> <!-- 底部空白占位 -->
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* 定制滚动条 */
::-webkit-scrollbar {
  width: 4px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: #ccc;
  border-radius: 4px;
}

/* 选择器中间线 */
.date-picker-container {
  position: relative;
}

.date-picker-container::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 40px;
  transform: translateY(-50%);
  border-top: 1px solid #f0f0f0;
  border-bottom: 1px solid #f0f0f0;
  pointer-events: none;
  z-index: 1;
  background-color: rgba(255, 248, 240, 0.3); /* 淡橙色背景 */
}

/* 移除原先在每个滚动容器上的样式 */
.flex-1.overflow-y-auto::after {
  display: none;
}

/* 设置选择器整体样式 */
.bg-white {
  border-radius: 12px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

/* 按钮样式 */
button.text-orange-500 {
  color: #f56c23;
}

button.bg-orange-50 {
  background-color: #fff8f2;
}

/* 选中项的样式 */
.selected {
  color: #f56c23 !important;
  font-weight: bold;
  position: relative;
}

.selected::after {
  content: '';
  position: absolute;
  width: 4px;
  height: 4px;
  background-color: #f56c23;
  border-radius: 50%;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
}
</style>